home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir37 / ms_sh23s.zip / SRC / SH0.ASM < prev    next >
Assembly Source File  |  1994-08-26  |  31KB  |  1,842 lines

  1.     TITLE   sh0.asm
  2.     NAME    sh0
  3.     .8087
  4.  
  5. ; MS-DOS SHELL - Swapper
  6. ;
  7. ; MS-DOS SHELL - Copyright (c) 1990,4 Data Logic Limited
  8. ;
  9. ; This code is subject to the following copyright restrictions:
  10. ;
  11. ; 1.  Redistribution and use in source and binary forms are permitted
  12. ;     provided that the above copyright notice is duplicated in the
  13. ;     source form and the copyright notice in file sh6.c is displayed
  14. ;     on entry to the program.
  15. ;
  16. ; 2.  The sources (or parts thereof) or objects generated from the sources
  17. ;     (or parts of sources) cannot be sold under any circumstances.
  18. ;
  19. ;    $Header: /usr/users/istewart/shell/sh2.3/Release/RCS/sh0.asm,v 2.6 1994/08/25 20:58:47 istewart Exp $
  20. ;
  21. ;    $Log: sh0.asm,v $
  22. ;    Revision 2.6  1994/08/25  20:58:47  istewart
  23. ;    MS Shell 2.3 Release
  24. ;
  25. ;    Revision 2.5  1994/01/11  17:55:25  istewart
  26. ;    Release 2.3 Beta 0 patches
  27. ;
  28. ;    Revision 2.4  1993/11/09  10:39:49  istewart
  29. ;    Beta 226 checking
  30. ;
  31. ;    Revision 2.3  1993/08/25  16:03:57  istewart
  32. ;    Beta 225 - see Notes file
  33. ;
  34. ;    Revision 2.2  1993/06/14  11:00:54  istewart
  35. ;    More changes for 223 beta
  36. ;
  37. ;    Revision 2.1  1992/07/16  14:33:34  istewart
  38. ;    Beta 212 Baseline
  39. ;
  40. ;    Revision 2.0  1992/04/13  17:39:45  Ian_Stewartson
  41. ;    MS-Shell 2.0 Baseline release
  42. ;
  43. ;
  44. ;
  45.  
  46. ;
  47. ; Segment declarations
  48. ;
  49.  
  50. SH0_TEXT    segment word public 'CODE'
  51. SH0_TEXT    ends
  52.  
  53. _DATA        segment word public 'DATA'
  54. _DATA        ends
  55.  
  56. CONST        segment word public 'CONST'
  57. CONST        ends
  58.  
  59. _BSS        segment word public 'BSS'
  60. _BSS        ends
  61.  
  62. DGROUP        group    CONST, _BSS, _DATA
  63. ;DGROUP        group    _BSS, _DATA
  64.  
  65. C_ETEXT        segment word public 'ENDCODE' 
  66. C_ETEXT        ends 
  67.  
  68. ;
  69. ; Declare external functions and data
  70. ;
  71.  
  72. IFDEF __TURBOC__
  73.     extrn    __IOERROR:far
  74. ELSE
  75.     extrn    __maperror:far
  76. ENDIF
  77.     extrn    _errno:word
  78.     extrn    __psp:word
  79.  
  80. ;
  81. ; Declare end of text variable.  The ENDCODE segment appears to be the last
  82. ; code segment loaded by the Microsoft loader
  83. ;
  84.  
  85. C_ETEXT        segment word public 'ENDCODE' 
  86.         public    cetext
  87. cetext        equ    $
  88. C_ETEXT        ends 
  89.  
  90. ;
  91. ; Start of the spawn function
  92. ;
  93.  
  94. SH0_TEXT    segment
  95.         assume  cs: SH0_TEXT, ds: NOTHING, ss: DGROUP
  96.  
  97. ;
  98. ; For this function, all the code and data space are in the code space
  99. ;
  100.         public    _cmd_line
  101.         public    _path_line
  102.         public    _SW_intr
  103.         public    _SW_Blocks
  104.         public    _SW_SBlocks
  105.         public    _SW_fp
  106.         public    _SW_EMstart
  107.         public    _SW_Mode
  108.         public    _SW_EMSFrame
  109.         public    _SW_Int00
  110.         public    _SW_Int23
  111.         public    _SW_Int24
  112.         public    _SW_XMS_Driver
  113.         public    _SW_XMS_Gversion
  114.         public    _SW_XMS_Allocate
  115.         public    _SW_XMS_Free
  116.         public    _SW_XMS_Available 
  117.         public    _Poll_Keyboard
  118.         public    _etext
  119.         public    _SW_Pwrite
  120.         public    _SW_I23_InShell
  121.         public    _SW_MinESpace
  122.  
  123.  
  124. _cmd_line    db    129 dup (?)    ; Command line
  125. _path_line    db    80 dup (?)    ; Path line
  126. _etext        dw    seg cetext    ; End of text segment
  127. _SW_Blocks    dw    0        ; Number of blocks to read/write
  128. _SW_SBlocks    dw    0        ; Short Number of blocks to read/write
  129. _SW_fp        dw    0ffffH        ; File ID
  130. _SW_Pwrite    dw    0        ; Partial write to disk?
  131. _SW_EMstart    dd    0100000H    ; Default Extended Mem start
  132. _SW_Mode    dw    0        ; Type of swapping to do
  133.                     ;   1 - disk
  134.                     ;   2 - Extended memory
  135.                     ;   3 - EMS driver
  136.                     ;   4 - XMS driver
  137. _SW_EMSFrame    dw    0        ; EMS Frame segment
  138. _SW_intr    dw    0        ; Interrupt 23 detected.
  139. _SW_MinESpace    dw    0        ; Minimum Environment space
  140. _SW_XMS_Driver    dd    0        ; XMS Driver Interface
  141. _SW_I23_InShell    db    0        ; In shell flag for Interrupt 23
  142.  
  143. ;
  144. ; Some addition variables
  145. ;
  146.  
  147. SW_LMstart    dd    0        ; Low Mem start for Extended Mem swap
  148. N_mcb        dw    0        ; Start write address
  149. Result        dw    0        ; Return value
  150.  
  151. ;
  152. ; Stack save pointers
  153. ;
  154.  
  155. S_ss        dw    0            ; Save Stack pointers
  156. S_sp        dw    0
  157. S_di        dw    0            ; Save DI, SI
  158. S_si        dw    0
  159. S_ds        dw    0            ; Save the original DS
  160.  
  161. ;
  162. ; Two blank FCB
  163. ;
  164.  
  165. FCB1        dw    16    dup (?)
  166. FCB2        dw    16    dup (?)
  167.  
  168. ;
  169. ; XMS Driver Move structure
  170. ;
  171.  
  172. XMS_DIF        equ    $
  173. XMS_Length    dd    0            ; Number of bytes
  174. XMS_SHandle    dw    0            ; Source Handler
  175. XMS_Soffset    dd    0            ; Source Offset
  176. XMS_DHandle    dw    0            ; Destination Handler
  177. XMS_Doffset    dd    0            ; Destination Offset
  178.  
  179. ;
  180. ; Extended Memory Global Descriptor tables
  181. ;
  182.         org    XMS_DIF
  183. GD_table    equ    $
  184. GDT_Dummy    dw    4    dup (0)        ; Dummy
  185. GDT_self    dw    4    dup (0)        ; For self
  186. GDT_src        equ    $            ; Source
  187.         dw    04000H            ; Length - 16K bytes
  188. GDT_src_low    dw    0            ;     Low Order address
  189. GDT_src_high    db    0            ;     High Order address
  190.         db    093h            ;     Access Rights
  191.         dw    0            ;     Reserved
  192. GDT_dest    equ    $            ; Destination
  193.         dw    04000H            ;     Length - 16K bytes
  194. GDT_dest_low    dw    0            ;     Low Order address
  195. GDT_dest_high    db    0            ;     High Order address
  196.         db    093h            ;     Access Rights
  197.         dw    0            ;     Reserved
  198. GDT_bios    dw    4    dup (0)        ; Bios
  199. GDT_stack    dw    4    dup (0)        ; Stack
  200.  
  201. ;
  202. ; Execute interrupt structure
  203. ;
  204.  
  205. exec_parms    equ    $
  206. exec_env    dw    0
  207.         dw    offset _cmd_line    ; Command line address
  208. exec_cseg    dw    ?
  209.         dw    offset FCB1        ; FCB1 address
  210. exec_f1seg    dw    ?
  211.         dw    offset FCB2        ; FCB1 address
  212. exec_f2seg    dw    ?
  213.  
  214. Swap_PANIC    db    'PANIC: Swap file re-load error - REBOOT', 0aH, 0dH
  215.         db    '$'
  216.  
  217. Swap_DZERO    db    'PANIC: Divide by zero', 0aH, 0dH
  218.         db    '$'
  219.  
  220. ;
  221. ; OK - exec requires a local stack, cause some programs overwrite it
  222. ;
  223.         even
  224.         db    398 dup (0)
  225. Local_Stack:
  226.         dw    0
  227.  
  228. ;
  229. ; Code starts
  230. ;
  231.     public    _SA_spawn
  232.  
  233. SA_spawn1    proc    far
  234.     mov    ds, word ptr cs:exec_env    ; Load Env seg.
  235.     xor    si, si                ; Clear start offset
  236.  
  237. ;
  238. ; Copy into Env Seg
  239. ;
  240.  
  241. $Copy_Env:
  242.     les    bx, dword ptr ss:[bp + 6]    ; Check for end of loop
  243.     mov    ax, word ptr es:[bx + 0]
  244.     or    ax, word ptr es:[bx + 2]
  245.     je    $Copy_End
  246.  
  247. ;
  248. ; Save start address
  249. ;
  250.     add    word ptr ss:[bp + 6], 4        ; Increment environment by 4
  251.  
  252.     mov    cx, word ptr es:[bx + 0]    ; Load address of cur Env string
  253.     mov    ax, word ptr es:[bx + 2]    ; into es:bx
  254.     mov    es, ax
  255.     mov    bx, cx
  256.  
  257. ;
  258. ; Copy this value
  259. ;
  260.  
  261. $Copy_Val:
  262.     mov    al, byte ptr es:[bx]    ; Copy across
  263.     mov    byte ptr ds:[si], al
  264.     inc    bx            ; Increment pointers
  265.     inc    si
  266.     or    al, al
  267.     jne    $Copy_Val
  268.     jmp    $Copy_Env
  269.  
  270. ;
  271. ; Set up exec parameter block     - DS is on stack
  272. ;
  273. $Copy_End:
  274.     xor    ax, ax
  275.     mov    word ptr ds:[si], ax    ; Terminate environment
  276.     add    si, 2
  277.  
  278.     cmp    si, word ptr cs:_SW_MinESpace    ;    Enough space ?
  279.     jge    $NoMoreE
  280.     mov    si, word ptr cs:_SW_MinESpace
  281.  
  282. ;
  283. ; Set up new program length
  284. ;
  285. $NoMoreE:
  286.     add    si, 16            ; Round up paras
  287.     mov    dx, si            ; Save end offset in DX
  288.     mov    bx, ds
  289.  
  290.     mov    cl, 4
  291.     shr    si, cl            ; # paras used by Env
  292.     add    si, bx            ; End para number
  293.  
  294.     mov    bx, word ptr cs:N_mcb    ; Load our MCB address in BX
  295.     mov    ax, bx
  296.     inc    ax
  297.     sub    si, ax
  298.     mov    cx, si            ; Save new max paras in CX
  299.  
  300. ;
  301. ; Use interrupt 4a to shrink memory.  First release all memory above us.
  302. ;
  303.     push    ax
  304.     push    cx            ; Save Max paras and location
  305.     mov    ds, bx            ; Set up the segement for MCB
  306.     mov    cx, word ptr ds:3    ; Get the MCB length
  307.  
  308. ; Are we the only one in the chain?
  309.  
  310.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  311.     jz    $Shrink_First
  312.  
  313. ;
  314. ; Loop round releasing memory blocks
  315. ;
  316. ;    CX - original length of block;
  317. ;    DS - segement of the previous block
  318. ;
  319. $Shrink_Next:
  320.     mov    ax, ds            ; Move to the next block
  321.     add    cx, ax
  322.     inc    cx
  323.     mov    ds, cx
  324.  
  325.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  326.     jz    $Shrink_First
  327.  
  328.     mov    cx, word ptr ds:3    ; Save the length of this block
  329.  
  330.     mov    ax, ds            ; Advance to the block itself
  331.     inc    ax
  332.     mov    es, ax            ; Set up Block address
  333.  
  334.     mov    ah, 049H
  335.     int    021H
  336.     jmp    $Shrink_Next
  337.  
  338. ;
  339. ;    Shrink the PSP segment
  340. ;
  341.  
  342. $Shrink_First:
  343.     pop    cx
  344.     pop    ax
  345.         mov    es, ax            ; Set PSP address
  346.     mov    bx, cx            ; Set max length
  347.     mov    ah, 04aH
  348.     int    021H
  349.  
  350. ;
  351. ; Execute function
  352. ;
  353.  
  354.     mov    word ptr cs: S_sp, sp    ; Save the current stack
  355.     mov    word ptr cs: S_ss, ss
  356.  
  357. ;
  358. ; Move to the local stack so that it doesn't get overwritten.
  359. ;
  360.     mov    ax, cs
  361.     cli
  362.     mov    sp, offset Local_Stack
  363.     mov    ss, ax
  364.     sti
  365.  
  366. ; Clear out Interrupts
  367.  
  368.     mov    ah, 00bH        ; Check Keyboard status
  369.     int    021H
  370.  
  371. ;
  372. ;  Check for interrupt 23 detected
  373. ;
  374.     mov    ax, word ptr cs:_SW_intr
  375.     or    ax, ax
  376.     jz    $I23_Cf            ; No - continue;
  377.  
  378. ;
  379. ; Interrupt 23 detected - abort
  380. ;
  381.     mov    ax, cs            ; Set up for reload
  382.     cli
  383.     mov    sp, offset Local_Stack
  384.     mov    ss, ax
  385.     sti
  386.  
  387.     mov    ds, word ptr cs:S_ds    ; Restore DS
  388.     xor    ax, ax
  389.     jmp    $Exec_Complete
  390.  
  391. ;
  392. ; No interrupts - continue
  393. ;
  394. $I23_Cf:
  395.     mov    ax, cs            ; Set up segments
  396.     mov    es, ax
  397.     mov    ds, ax
  398.  
  399.     mov    ax, 04b00H        ; Load and execute function
  400.     mov    dx, offset _path_line    ; Load path
  401.     mov    bx, offset exec_parms    ; Load the execute structure
  402.     mov    byte ptr cs:_SW_I23_InShell, 1    ; Set not shell flag 
  403.     int    021H
  404.     mov    byte ptr cs:_SW_I23_InShell, 0    ; Set in shell flag 
  405.  
  406. ; Disable interrupts while we restore the stack to the local one
  407.  
  408.     mov    ax, cs
  409.     cli
  410.     mov    sp, offset Local_Stack
  411.     mov    ss, ax
  412.     sti
  413.  
  414. ;
  415. ; Did an error occur?
  416. ;
  417.     jnc    $Exec_OK
  418.  
  419. ;
  420. ; Error
  421. ;
  422.  
  423. $Map_error:
  424.     mov    ds, word ptr cs:S_ds    ; Restore DS
  425. IFDEF __TURBOC__
  426.     xor    ah, ah
  427.     push    ax
  428.     call    far ptr __IOERROR    ; Map the error
  429. ELSE
  430.     mov    ah, al
  431.     call    far ptr __maperror    ; Map the error
  432. ENDIF
  433.  
  434. $Exec_Error:
  435.     mov    ax, 0FFFFH
  436.     jmp    $Exec_Complete
  437.  
  438. ;
  439. ; No - get the exit code and check for interrupts
  440. ;
  441.  
  442. $Exec_OK:
  443.     mov    ax, 04d00H
  444.     int    021H
  445.     dec    ah            ; Interrupt termination ?
  446.     jnz    $Exec_OK1
  447.  
  448.     inc    word ptr ds:_SW_intr    ; Set Interrupt 23 detected.
  449.  
  450. $Exec_OK1:
  451.     xor    ah, ah
  452.  
  453. ;
  454. ; Save the result code
  455. ;
  456.  
  457. $Exec_Complete:
  458.     mov    word ptr cs:Result, ax        ; Save response
  459.  
  460. ;
  461. ; Very Dangerous - Restore Environment
  462. ;
  463. ;     Seek to 0x4000 in file
  464. ;
  465.     mov    bx, word ptr cs:_SW_fp        ; Load File Handler
  466.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  467.     dec    ax
  468.     jnz    $Seek_OK
  469.  
  470. ; Seek in file to skip 16K
  471.  
  472.     mov    dx, 04000H
  473.     call    $Seek_Disk
  474.  
  475. ;
  476. ;     Load from N_mcb:0x4000 to end of file.
  477. ;
  478.  
  479. $Seek_OK:
  480.     mov    si, word ptr cs:_SW_Blocks    ; Load number of transfers
  481.     dec    si                ; Skip first block
  482.  
  483. ;
  484. ; set up ES register with start of load
  485. ;
  486.     mov    ax, word ptr cs:N_mcb    ; Load the start address
  487.     add    ax, 0400H
  488.     mov    ds, ax
  489.  
  490. ; load up extended memory GDT for destination
  491.  
  492.     call    $GDT_reload
  493.     call    $Inc_Extend            ; Increment addresses by 16K
  494.  
  495. ;
  496. ; Check for end of copy    - BX - File Handler for disk
  497. ;
  498.  
  499. $Read_loop:
  500.     or    si, si
  501.     je    $Read_Complete
  502.  
  503. ; OK - Copy next 0x4000 bytes - switch on device
  504.  
  505.     mov    ax, word ptr cs: _SW_Mode
  506.     dec    ax
  507.     jz    $R_disk
  508.     dec    ax
  509.     jz    $R_extend
  510.     dec    ax
  511.     jz    $R_expand
  512.  
  513. ;
  514. ; Read from XMS driver.  In this case, we do one read and let the driver
  515. ; sort out the blocking
  516. ;
  517.     call    $Read_XMS
  518.     jmp     $Read_Complete
  519.  
  520. ; Read from disk
  521.  
  522. $R_disk:
  523.     call    $Read_disk
  524.     jmp    $Read_loop
  525.  
  526. ; Read from extended memory
  527.  
  528. $R_extend:
  529.     call    $Read_extend
  530.     jmp    $Read_loop
  531.  
  532. ; Read from expanded memory
  533.  
  534. $R_expand:
  535.     call    $Read_EMS
  536.     jmp    $Read_loop
  537.  
  538. ;
  539. ; Re-load is now complete, Restore original stack which has just been
  540. ; reloaded.  BX contains FP
  541. ;
  542.  
  543. $Read_Complete:
  544.     cli
  545.     mov    sp, word ptr cs: S_sp        ; Save the current stack
  546.     mov    ss, word ptr cs: S_ss
  547.     sti
  548.  
  549. ;  Save exit code
  550.  
  551.     push    word ptr cs:Result        ; Save response
  552.     push    word ptr cs:_SW_intr        ; and interrupt flag
  553.  
  554. ;
  555. ; Read in the first block - BX - File Handler
  556. ;
  557.  
  558.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  559.     dec    ax
  560.     jnz    $Seek1_OK
  561.  
  562. ; Seek to 0 in file
  563.  
  564.     xor    dx, dx
  565.     call    $Seek_Disk
  566.  
  567. ;
  568. ;     Load one block at N_mcb:0x0000
  569. ;
  570. $Seek1_OK:
  571.     mov    ds, word ptr cs:N_mcb        ; Load the start address
  572.     call    $GDT_reload            ; Load the GDT for extend mem
  573.  
  574.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  575.     dec    ax
  576.     jz    $R1_Disk
  577.     dec    ax
  578.     jz    $R1_Extend
  579.     dec    ax
  580.     jz    $R1_Expand
  581.  
  582.     mov    si, 1                ; Read one block
  583.     call    $Read_XMS
  584.     jmp    $Read1_OK
  585.  
  586. $R1_Disk:
  587.     call    $Read_disk
  588.     jmp    $Read1_OK
  589.  
  590. $R1_Extend:
  591.     call    $Read_extend
  592.     jmp    $Read1_OK
  593.  
  594. $R1_Expand:
  595.     mov    si, word ptr cs:_SW_Blocks    ; Read first block
  596.     call    $Read_EMS
  597.  
  598. ;
  599. ; Complete - load error code and return
  600. ;
  601.  
  602. $Read1_OK:
  603.     pop    word ptr cs:_SW_intr        ; Restore interrupt flag
  604.     pop    ax
  605.  
  606. ;
  607. ; Exit function - Restore Control Interrupt handler
  608. ;
  609.  
  610. $SA_spawn_Exit:
  611.  
  612.     mov    di, word ptr cs:S_di        ; Restore saved registers
  613.     mov    si, word ptr cs:S_si
  614.     mov    ds, word ptr cs:S_ds
  615.  
  616.     mov    sp, bp
  617.     pop    bp
  618.     ret
  619.  
  620. SA_spawn1    endp
  621.  
  622. ;
  623. ; READ XMS DRIVER FUNCTION
  624. ;
  625. ;    BX - file handler
  626. ;    SI - Block count
  627. ;    DS - Output data segement
  628. ;
  629. $Read_XMS    proc    near
  630.     xor    ax, ax
  631.     mov    word ptr cs:XMS_SHandle, bx    ; Source - XMS
  632.     mov    word ptr cs:XMS_DHandle, ax    ; Dest - normal memory
  633.  
  634.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset - zero
  635.     mov    word ptr cs:XMS_Soffset + 2, ax
  636.  
  637.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset DS:0
  638.     mov    ax, ds
  639.     mov    word ptr cs:XMS_Doffset + 2, ax
  640.  
  641.     cmp    si, 1                ; If first block, the
  642.     jz    $Read_X1            ; source offset is
  643.                         ; 4000H
  644.     mov    word ptr cs:XMS_Soffset, 04000H
  645.  
  646. ;
  647. ; Set up number of bytes: si * 16 * 1024
  648. ;
  649.  
  650. $Read_X1:
  651.     mov    ax, si
  652.     mov    dx, si
  653.     mov    cl, 14
  654.     shl    ax, cl
  655.     mov    cl, 2
  656.     shr    dx, cl
  657.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  658.     mov    word ptr cs:XMS_Length + 2, dx
  659.  
  660.     mov    ah, 0BH                ; Set up parameters
  661.     mov    dx, cs
  662.     mov    ds, dx
  663.     mov    si, offset XMS_DIF
  664.     call    cs:[_SW_XMS_Driver]
  665.     or    ax, ax
  666.     jnz     $Read_XMS1
  667.     jmp    Load_Error            ; XMS error - abort
  668.  
  669. $Read_XMS1:
  670.     ret
  671.  
  672. $Read_XMS    endp
  673.  
  674. ;
  675. ; READ DISK FUNCTION
  676. ;
  677. ;    BX - file handler
  678. ;    SI - Block count
  679. ;    DS - Output data segement
  680. ;
  681.  
  682. $Read_disk    proc    near
  683.  
  684.     mov    ax, 03f00H        ; Set up to read
  685.     mov    cx, 04000H        ; Load count
  686.     xor    dx, dx            ; Clear start address
  687.  
  688.     int    021H            ; Read the data
  689.  
  690.     jnc    $Read_OK        ; NO - abort
  691.     jmp    Load_Error        ; Abort - swap file error
  692.  
  693. ;
  694. ; Read OK - next block
  695. ;
  696.  
  697. $Read_OK:
  698.     dec    si            ; Decrement block count
  699.     mov    ax, ds            ; Increment offset
  700.     add    ax, 0400H
  701.     mov    ds, ax
  702.     ret
  703.  
  704. $Read_disk    endp
  705.  
  706. ;
  707. ; READ EMS FUNCTION
  708. ;
  709. ;    BX - file handler
  710. ;    SI - Block count - counts from max
  711. ;    DS - Output data segement
  712. ;
  713.  
  714. $Read_EMS    proc    near
  715.  
  716.     call    $map_ems_page        ; Map in the current EMS page
  717.     jnz    Load_Error
  718.  
  719.     push    ds            ; Save DS and SI
  720.     push    si
  721.     mov    ax, ds
  722.     mov    es, ax
  723.     mov    ds, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  724.     xor    si, si            ; Clear start
  725.     xor    di, di
  726.     mov    cx, 02000H        ; move 16K
  727.     pushf                ; Save direction flag
  728.     cld
  729.     rep movsw
  730.     popf                ; Restore direction flag
  731.     pop    si            ; And DS, SI
  732.     pop    ds
  733.     jmp    $Read_OK        ; Increment DS and dec SI
  734.  
  735. $Read_EMS    endp
  736.  
  737. ;
  738. ; MAP IN THE CURRENT EMS PAGE
  739. ;
  740. ;    BX - file handler
  741. ;    SI - Block count - counts from max
  742. ;    DS - Output data segement
  743. ;
  744.  
  745. $map_ems_page    proc    near
  746.  
  747.     push    bx            ; Need to save BX
  748.     mov    ax, 04400h        ; Map into physical page zero
  749.     mov    dx, bx            ; Set up handler
  750.     mov    bx, word ptr cs: _SW_Blocks
  751.     sub    bx, si
  752.  
  753.     int    067H
  754.     pop    bx
  755.  
  756.     or    ah, ah
  757.     ret
  758.  
  759. $map_ems_page    endp
  760.  
  761. ;
  762. ; DISK SEEK FUNCTION
  763. ;
  764. ;    BX - file handler
  765. ;    DX - offset
  766. ;
  767. $Seek_Disk    proc    near
  768.  
  769.     mov    ax, 04200H        ; Set seek
  770.     xor    cx, cx
  771.     int    021H
  772.     jc    Load_Error        ; Abort - swap file error
  773.     ret
  774.  
  775. $Seek_Disk    endp
  776.  
  777. ;
  778. ; PANIC - Abort
  779. ;
  780.  
  781. Load_Error    proc    near
  782.  
  783.     mov    di, offset Swap_PANIC
  784.     mov    bx, cs
  785.     mov    ds, bx
  786.     call    I24_Display
  787. $Wait_L:
  788.     sti
  789.     hlt
  790.     jmp    $Wait_L
  791.  
  792. Load_Error    endp
  793.  
  794. ;
  795. ;  WRITE EXTENDED MEMORY
  796. ;
  797. ;    SI - Block count
  798. ;
  799. $Write_extend    proc    near
  800.  
  801.     push    si            ; Save SI (block counter)
  802.     mov    cx, 02000H        ; Copy a 16K block
  803.     mov    ax, cs            ; Set up GDT address
  804.     mov    es, ax
  805.     mov    si, offset GD_table
  806.  
  807.     mov    ah, 087H        ; EMS function
  808.     int    015H
  809.     pop    si
  810.     ret
  811.  
  812. $Write_extend    endp
  813.  
  814. ;
  815. ;  READ FROM EXTENDED MEMORY
  816. ;
  817. ;    SI - Block count
  818. ;
  819.  
  820. $Read_extend    proc    near
  821.  
  822.     call    $Write_extend
  823.     jc    Load_Error        ; NO - abort
  824.  
  825.     dec    si            ; Decrement block count
  826.  
  827. $Read_extend    endp
  828.  
  829. ;
  830. ; INCREMENT Extended MEMORY GDT
  831. ;
  832. ;    AX - used
  833. ;
  834. $Inc_Extend    proc    near
  835.  
  836.     mov    ax, 04000H        ; Increment address by 16K
  837.     add    word ptr cs:GDT_dest_low, ax
  838.     adc    byte ptr cs:GDT_dest_high, 0
  839.     add    word ptr cs:GDT_src_low, ax
  840.     adc    byte ptr cs:GDT_src_high, 0
  841.     ret
  842.  
  843. $Inc_Extend    endp
  844.  
  845. ;
  846. ; LOAD SOURCE GDT ADDRESS
  847. ;
  848. ;    AX - low order
  849. ;    DL - high order
  850. ;
  851. $GDT_src_load    proc    near
  852.  
  853.  
  854.     mov    word ptr cs:GDT_src_low, ax
  855.     mov    byte ptr cs:GDT_src_high, dl
  856.     ret
  857.  
  858. $GDT_src_load    endp
  859.  
  860. ;
  861. ; LOAD DESTINATION GDT ADDRESS
  862. ;
  863. ;    AX - low order
  864. ;    DL - high order
  865. ;
  866. $GDT_dest_load    proc    near
  867.  
  868.     mov    word ptr cs:GDT_dest_low, ax
  869.     mov    byte ptr cs:GDT_dest_high, dl
  870.     ret
  871.  
  872. $GDT_dest_load    endp
  873.  
  874. ;
  875. ; LOAD the GDT for reloading
  876. ;
  877.  
  878. $GDT_reload    proc    near
  879.     mov    ax, word ptr cs:_SW_EMstart     ; Load Full start address
  880.     mov    dl, byte ptr cs:_SW_EMstart + 2
  881.     call    $GDT_src_load
  882.  
  883.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  884.     mov    dl, byte ptr cs:SW_LMstart + 2
  885.     call    $GDT_dest_load
  886.     ret
  887. $GDT_reload    endp
  888.  
  889. ;
  890. ; CONTROL C INTERRUPT HANDLER - IGNORE
  891. ;
  892.  
  893. _SW_Int23    proc    far
  894.     inc    word ptr cs:_SW_intr    ; Set Interrupt 23 detected.
  895.     cmp    byte ptr cs:_SW_I23_InShell, 0    ; are we in the shell?
  896.     jz    $SA_Ins
  897.  
  898. ; In another program - move the stack around
  899.  
  900.     stc
  901.     ret
  902.  
  903.  
  904. ; In shell - ignore interrupt 23 for the moment
  905.  
  906. $SA_Ins:
  907.     iret
  908.  
  909. _SW_Int23    endp
  910.  
  911. ;
  912. ; DIVIDE BY ZERO INTERRUPT HANDLER - Output message
  913. ;
  914.  
  915. _SW_Int00    proc    far
  916.  
  917.     mov    ax, 00900H
  918.     mov    dx, offset Swap_DZERO
  919.     mov    bx, cs
  920.     mov    ds, bx
  921.     int    021H
  922.  
  923.     mov    ax, 04CFFh        ; Exit
  924.     int    021H
  925.  
  926. _SW_Int00    endp
  927.  
  928. ;
  929. ; INTERRUPT 24 - ERROR HANDLER - Output message
  930. ;
  931. ;    AH - Bit  7    = 0 Disk error
  932. ;            = 1 FAT error if block device
  933. ;                Error code in DI if character device
  934. ;      Bit  6    UNUSED
  935. ;      Bit  5    = 1 Ignore allowed
  936. ;      Bit  4    = 1 Retry allowed
  937. ;      Bit  3    = 1 Fail allowed
  938. ;      Bits 2 & 1    = Disk Area
  939. ;      Bit  0    = 1 Writing error
  940. ;    AL         = Disk drive number
  941. ;    DI            = Error code
  942. ;    BP:SI        = Header of device driver for which error occured
  943. ;
  944. ;
  945. ; Return
  946. ;    AL            = 0 Ignore Error
  947. ;            = 1 Retry operation
  948. ;            = 2 Abort program
  949. ;            = 3 Fail system call
  950. ;
  951.  
  952. I24_Errors    equ    $
  953. I24_EC00:    db    'Write-protect error$'
  954. I24_EC01:    db    'Unknown unit$'
  955. I24_EC02:    db    'Drive not ready$'
  956. I24_EC03:    db    'Unknown command$'
  957. I24_EC04:    db    'CRC error$'
  958. I24_EC05:    db    'Bad request structure length$'
  959. I24_EC06:    db    'Seek error$'
  960. I24_EC07:    db    'Unknown media type$'
  961. I24_EC08:    db    'Sector not found$'
  962. I24_EC09:    db    'Out of paper$'
  963. I24_EC0A:    db    'Write fault$'
  964. I24_EC0B:    db    'Read fault$'
  965. I24_EC0C:    db    'General failure$'
  966. I24_EC0D:    db    'Sharing violation$'
  967. I24_EC0E:    db    'Lock violation$'
  968. I24_EC0F:    db    'Invalid disk change$'
  969. I24_EC10:    db    'FCB unavailable$'
  970. I24_EC11:    db    'Sharing buffer overflow$'
  971. I24_ECUK:    db    'Unknown error$'
  972.  
  973. ;
  974. ; Error message address table
  975. ;
  976.  
  977. I24_ECTABLE:    dw    offset I24_EC00
  978.         dw    offset I24_EC01
  979.         dw    offset I24_EC02
  980.         dw    offset I24_EC03
  981.         dw    offset I24_EC04
  982.         dw    offset I24_EC05
  983.         dw    offset I24_EC06
  984.         dw    offset I24_EC07
  985.         dw    offset I24_EC08
  986.         dw    offset I24_EC09
  987.         dw    offset I24_EC0A
  988.         dw    offset I24_EC0B
  989.         dw    offset I24_EC0C
  990.         dw    offset I24_EC0D
  991.         dw    offset I24_EC0E
  992.         dw    offset I24_EC0F
  993.         dw    offset I24_EC10
  994.         dw    offset I24_EC11
  995.         dw    offset I24_ECUK
  996.  
  997. I24_ECON:    db    ' when $'
  998. I24_ECREAD:    db    'reading $'
  999. I24_ECWRITE:    db    'writing $'
  1000. I24_ECDEVICE:    db    'device $'
  1001. I24_ECDISK:    db    'disk $'
  1002. I24_EABORT:    db    'Abort$'
  1003. I24_EFAIL:    db    ', Fail$'
  1004. I24_EIGNORE:    db    ', Ignore$'
  1005. I24_ERETRY:    db    ', Retry$'
  1006. I24_EDRIVE:    db    '?:$'
  1007. I24_EQUESTION    db    '? $'
  1008. I24_RESPONSE:    db    ' '
  1009. I24_ENL:    db    0dH, 0aH, '$'
  1010. I24_EBELL:    db    07H, '$'
  1011. I24_EDNAME:    db    '12345678:$'
  1012. I24_EXTECODE:    db    0dH, 0aH, '(Extended Code: '
  1013. I24_E_AL:    db    '  h'
  1014.         db    ' Class: '
  1015. I24_E_BH:    db    '  h'
  1016.         db    ' Action: '
  1017. I24_E_BL:    db    '  h'
  1018.         db    ' Locus: '
  1019. I24_E_CH:    db    '  h)', 0dH, 0aH, '$'
  1020.  
  1021. ;
  1022. ; Save DS, ES, BX, CX, DX
  1023. ;
  1024. _SW_Int24    proc    far
  1025.     push    ds        ; Save registers
  1026.     push    es
  1027.     push    bx
  1028.     push    cx
  1029.     push    dx
  1030.  
  1031.     push    cs        ; Set up data segment
  1032.     pop    ds
  1033.  
  1034.     mov    cx, ax        ; Save the error information in CX
  1035.  
  1036.     mov    di, offset I24_ENL
  1037.     call    I24_Display
  1038. ;
  1039. ; Get extended error codes
  1040. ;
  1041.     push    cx
  1042.     push    ds
  1043.     push    si
  1044.     push    bp
  1045.     mov    ah, 059H
  1046.     xor    bx, bx
  1047.     int    021H
  1048.     pop    bp
  1049.     pop    si
  1050.     pop     ds
  1051.     pop    cx
  1052.     sub    ax, 13H
  1053.     mov    di, ax
  1054.  
  1055. ;
  1056. ;  Check inside message range
  1057. ;
  1058.     cmp    di, 012H
  1059.     jb    SWI24a
  1060.     mov    di, 12H        ;new 'unknown error' entry
  1061.  
  1062. ;
  1063. ; Write the error message
  1064. ;
  1065.  
  1066. SWI24a:
  1067.     add    di, di
  1068.  
  1069.     mov    di, word ptr ds:I24_ECTABLE[di]
  1070.     call    I24_Display
  1071.  
  1072. ;
  1073. ; Output on message
  1074. ;
  1075.  
  1076.     mov    di, offset I24_ECON
  1077.     call    I24_Display
  1078.  
  1079. ;
  1080. ; Output reading or write message
  1081. ;
  1082.  
  1083.     mov    di, offset I24_ECWRITE
  1084.     test    ch, 01H
  1085.     jnz    SWI24b
  1086.     mov    di, offset I24_ECREAD
  1087.  
  1088. SWI24b:
  1089.     call    I24_Display
  1090.  
  1091. ;
  1092. ; Output device message
  1093. ;
  1094.  
  1095.     test    ch, 080H
  1096.     jz    SWI24c
  1097.  
  1098.     mov    di, offset I24_ECDEVICE
  1099.     call    I24_Display
  1100.  
  1101. ;
  1102. ; Output device name - up to eight characters
  1103. ;
  1104.  
  1105.     add    si, 0aH            ; Move to device name
  1106.     push    ds
  1107.     mov    ds, bp
  1108.     xor    di, di            ; Set counter
  1109.  
  1110. SWI24b1:
  1111.     mov    dl, byte ptr ds:[si]    ; Get next character in name
  1112.     cmp    dl, ' '
  1113.     jz    SWI24d
  1114.  
  1115.     mov    byte ptr cs:[I24_EDNAME + di], dl
  1116.  
  1117.     inc    si
  1118.     inc    di
  1119.     cmp    di, 8
  1120.     jnz    SWI24b1
  1121. ;
  1122. ; Append a : and $
  1123. SWI24d:
  1124.     pop    ds
  1125.     mov    byte ptr cs:[I24_EDNAME + di], ':'
  1126.     mov    byte ptr cs:[I24_EDNAME + 1 + di], '$'
  1127.     mov    di, offset I24_EDNAME
  1128.     jmp    SWI24e
  1129.  
  1130. ;
  1131. ; Write disk error
  1132. ;
  1133. SWI24c:
  1134.     mov    di, offset I24_ECDISK
  1135.     call    I24_Display
  1136.  
  1137.     mov    dl, cl
  1138.     add    dl, 'A'
  1139.     mov    byte ptr cs:I24_EDRIVE, dl
  1140.  
  1141.     mov    di, offset I24_EDRIVE
  1142. SWI24e:
  1143.     call    I24_Display
  1144.  
  1145. ;
  1146. ; Get extended error codes
  1147. ;
  1148.     push    cx
  1149.     push    ds
  1150.     mov    ah, 059H
  1151.     xor    bx, bx
  1152.     int    021H
  1153.  
  1154. ;
  1155. ; Save responses
  1156. ;
  1157.  
  1158.     mov    byte ptr cs:I24_E_AL, al
  1159.     mov    byte ptr cs:I24_E_BL, bl
  1160.     mov    byte ptr cs:I24_E_BH, bh
  1161.     mov    byte ptr cs:I24_E_CH, ch
  1162.     pop    ds
  1163.     pop    cx
  1164.  
  1165. ; Convert to display Hex.
  1166.  
  1167.     mov    di, offset I24_E_AL
  1168.     call    I24_Convert
  1169.     mov    di, offset I24_E_BL
  1170.     call    I24_Convert
  1171.     mov    di, offset I24_E_BH
  1172.     call    I24_Convert
  1173.     mov    di, offset I24_E_CH
  1174.     call    I24_Convert
  1175.     mov    di, offset I24_EXTECODE
  1176.     call    I24_Display
  1177. ;
  1178. ; Output Options 
  1179. ;
  1180.     mov    di, offset I24_EABORT
  1181.     call    I24_Display
  1182.  
  1183.     test    ch, 020H        ; Ignore allowed ?
  1184.     jz    SWI24f
  1185.     mov    di, offset I24_EIGNORE
  1186.     call    I24_Display
  1187.  
  1188. SWI24f:
  1189.     test    ch, 010H        ; Retry allowed ?
  1190.     jz    SWI24g
  1191.     mov    di, offset I24_ERETRY
  1192.     call    I24_Display
  1193.  
  1194. SWI24g:
  1195.     test    ch, 08H            ; Fail allowed ?
  1196.     jz    SWI24h
  1197.     mov    di, offset I24_EFAIL
  1198.     call    I24_Display
  1199.  
  1200. ;
  1201. ; Append a question mark.
  1202. ;
  1203.  
  1204. SWI24h:
  1205.     mov    di, offset I24_EQUESTION
  1206.     call    I24_Display
  1207.  
  1208. ;
  1209. ; Get the valid key codes
  1210. ;
  1211. SWI24j:
  1212.     xor    ax, ax            ; Read a keyboard character
  1213.     int    16H
  1214.     and    al, 05fH        ; Upper case
  1215.  
  1216.     xor    ah, ah            ; Clear counter
  1217.     cmp    al, 'I'            ; Ignore ?
  1218.     jnz    SWI24k
  1219.     test    ch, 020H
  1220.     jnz    SWI24n
  1221. SWI24k:
  1222.     inc    ah
  1223.     cmp    al, 'R'            ; Retry ?
  1224.     jnz    SWI24l
  1225.     test    ch, 010H
  1226.     jnz    SWI24n
  1227. SWI24l:
  1228.     inc    ah
  1229.     cmp    al, 'A'            ; Abort ?
  1230.     jz    SWI24n
  1231.  
  1232.     inc    ah
  1233.     cmp    al, 'F'            ; Fail ?
  1234.     jnz    SWI24m
  1235.     test    ch, 08H
  1236.     jnz    SWI24n
  1237. SWI24m:
  1238.     mov    di, offset I24_EBELL
  1239.     call    I24_Display
  1240.     jmp    SWI24j
  1241.  
  1242. ;
  1243. ; OK - got code
  1244. ;
  1245. SWI24n:
  1246.     mov    cl, ah
  1247.     mov    byte ptr ds:I24_RESPONSE, al
  1248.     mov    di, offset I24_RESPONSE
  1249.     call    I24_Display
  1250.     mov    ax, cx
  1251.  
  1252. ;
  1253. ; Are we in the shell ?
  1254. ;
  1255.     cmp    byte ptr cs:_SW_I23_InShell, 0    ; Are we in the shell ? 
  1256.     jnz    $SW_int24a        ; No - no processing
  1257.  
  1258.     cmp    al, 02H            ; Abort?
  1259.     jnz    $SW_int24a        ; No - exit
  1260.  
  1261.     test    ah, 008h        ; If fail allowed - convert to fail
  1262.     jz    $SW_int24a
  1263.  
  1264.     mov    al, 003h        ; Fail system call
  1265.  
  1266. $SW_int24a:
  1267.     pop    dx            ; Restore registers
  1268.     pop    cx
  1269.     pop    bx
  1270.     pop    es
  1271.     pop    ds        
  1272.     iret
  1273. _SW_Int24    endp
  1274.  
  1275. ;
  1276. ; Convert Hex code to display code
  1277. ;
  1278. ; ds:di Offset of code to replace
  1279. ; ax is available
  1280. ;
  1281. I24_Convert    proc    near
  1282.     push    cx
  1283.     mov    al, byte ptr ds:[di]    ; Get the code
  1284.     mov    ah, al
  1285.     mov    cl, 4
  1286.     shr    ah, cl
  1287.     and    ah, 0fh
  1288.  
  1289.     cmp    ah, 10
  1290.     jb    I24_C1
  1291.     add    ah, 'A' - 10
  1292.     jmp    I24_C2
  1293. I24_C1:
  1294.     add    ah, '0'
  1295. I24_C2:
  1296.     mov    byte ptr ds:[di], ah
  1297.  
  1298. ; Now LSB
  1299.  
  1300.     and    al, 0fh
  1301.     cmp    al, 10
  1302.     jb    I24_C3
  1303.     add    al, 'A' - 10
  1304.     jmp    I24_C4
  1305. I24_C3:
  1306.     add    al, '0'
  1307. I24_C4:
  1308.     mov    byte ptr ds:[di + 1], al
  1309.     pop    cx
  1310.     ret
  1311. I24_Convert    endp
  1312. ;
  1313. ;  Display message function for Interrupt 24 processing
  1314. ;
  1315. ;  DS:DI message
  1316. ;  AX is available
  1317. ;
  1318.  
  1319. I24_Display    proc    near
  1320.     mov    ah, 08H            ; Get foreground colour
  1321.     xor    bx, bx
  1322.     int    10H
  1323.     mov    bl, ah
  1324.     and    bl, 07h
  1325.  
  1326. ;
  1327. ; Loop until a $ is hit, outputting the characters
  1328. ;
  1329. I24D:
  1330.     mov    al, byte ptr ds:[di]
  1331.     cmp    al, '$'
  1332.     jnz    I24Da
  1333.     ret
  1334.  
  1335. I24Da:
  1336.     push    di
  1337.     mov    ah, 0EH
  1338.     int    10H
  1339.     pop    di
  1340.     inc    di
  1341.     jmp    I24D
  1342.  
  1343. I24_Display    endp
  1344.  
  1345. ;
  1346. ;  Start of overwrite area for environment.  Align on a paragraph
  1347. ;
  1348. ;  Also the XMS driver functions used by SH3.C live here
  1349. ;
  1350.         ALIGN    16
  1351. Env_OWrite:
  1352.  
  1353. ;
  1354. ; XMS INTERFACE
  1355. ;
  1356. ; Get Version number.  Return the release number in AX
  1357. ;
  1358.  
  1359. _SW_XMS_Gversion    proc    far
  1360.  
  1361.     push    bp            ; Save stack info
  1362.     mov    bp, sp
  1363.  
  1364.     xor    ax, ax
  1365.     call    cs:[_SW_XMS_Driver]
  1366.  
  1367.     mov    sp, bp
  1368.     pop    bp
  1369.     ret
  1370.  
  1371. _SW_XMS_Gversion    endp
  1372.  
  1373. ;
  1374. ; Allocate N kbytes.  Return the Handler in AX or -1 and error code in
  1375. ; errno.
  1376. ;
  1377. ; Size will be in bp + 6.
  1378. ;
  1379.  
  1380. _SW_XMS_Allocate    proc    far
  1381.  
  1382.     push    bp            ; Save stack info
  1383.     mov    bp, sp
  1384.  
  1385.     mov    dx, word ptr ss:[bp + 6]
  1386.     mov    ah, 09H
  1387.     call    cs:[_SW_XMS_Driver]
  1388.     or    ax, ax
  1389.     jnz    $SW_A1
  1390.  
  1391. ;
  1392. ; Allocate Failed - return error code
  1393. ;
  1394.     xor    ax, ax
  1395.     dec    ax
  1396.     xor    bh, bh
  1397.     mov    word ptr ds:_errno, bx    ; Save error code
  1398.     jmp    $SW_A2
  1399.  
  1400. ;
  1401. ; Allocate OK - return handler
  1402. ;
  1403.  
  1404. $SW_A1:
  1405.     mov    ax, dx
  1406.  
  1407. $SW_A2:
  1408.     mov    sp, bp
  1409.     pop    bp
  1410.     ret
  1411.  
  1412. _SW_XMS_Allocate    endp
  1413.  
  1414. ;
  1415. ; Release handler.  Return 0 or error code.
  1416. ;
  1417. ; Handler will be in bp + 6.
  1418. ;
  1419.  
  1420. _SW_XMS_Free         proc    far
  1421.  
  1422.     push    bp            ; Save stack info
  1423.     mov    bp, sp
  1424.  
  1425.     mov    dx, word ptr ss:[bp + 6]
  1426.     mov    ah, 0AH
  1427.     call    cs:[_SW_XMS_Driver]
  1428.     or    ax, ax
  1429.     jnz    $SW_F1
  1430. ;
  1431. ; Free Failed - return error code
  1432. ;
  1433.     mov    al, bl
  1434.     jmp    $SW_F2
  1435.  
  1436. ;
  1437. ; Free OK - return zero
  1438. ;
  1439. $SW_F1:
  1440.     xor    ax, ax
  1441.  
  1442. $SW_F2:
  1443.     mov    sp, bp
  1444.     pop    bp
  1445.     ret
  1446.  
  1447. _SW_XMS_Free         endp
  1448.  
  1449. ;
  1450. ; Get available memory space.  Return 0 if failed.
  1451. ;
  1452.  
  1453.  
  1454. _SW_XMS_Available    proc    far
  1455.  
  1456.     push    bp            ; Save stack info
  1457.     mov    bp, sp
  1458.     mov    ah, 08H
  1459.     call    cs:[_SW_XMS_Driver]
  1460.     or    bl, bl
  1461.     jz    $SW_Avail1
  1462.  
  1463. ;
  1464. ; Free Failed - return zero
  1465. ;
  1466.     xor    ax, ax
  1467.  
  1468. $SW_Avail1:
  1469.     mov    sp, bp
  1470.     pop    bp
  1471.     ret
  1472.  
  1473. _SW_XMS_Available    endp
  1474.  
  1475. ;
  1476. ; Read Keyboard via interrupt 21 function 6 with polling for DESQView support.
  1477. ; Return Keyboard code in AL.
  1478. ;
  1479.  
  1480. _Poll_Keyboard    proc    far
  1481.     push    bp
  1482.     mov    bp, sp
  1483.     push    ds            ; Save the C registers
  1484.     push    es
  1485.     push    si
  1486.     push    di
  1487.  
  1488. ReadK1:
  1489.     mov    ah, 6            ; Read the keyboard
  1490.     mov    dl, 0ffH
  1491.     int    021H
  1492.     jnz    ReadK2            ; Got a keystroke!!
  1493.  
  1494.     mov    AX, 01000H        ; Failed - Release timeslice.
  1495.     int    015H
  1496.     jmp    ReadK1
  1497.  
  1498. ; Got a character - Get the keybaord status information
  1499.  
  1500. ReadK2:
  1501.     pop    di            ; Restore stack
  1502.     pop    si
  1503.     pop    es
  1504.     pop    ds
  1505.     mov    sp, bp
  1506.     pop    bp
  1507.     ret    
  1508.  
  1509. _Poll_Keyboard    endp
  1510.  
  1511. ;
  1512. ; Main Entry point.  This part can be overwritten by the environment
  1513. ;
  1514.  
  1515. _SA_spawn    proc    far
  1516.  
  1517.     push    bp
  1518.     mov    bp, sp
  1519.  
  1520. ;
  1521. ; Entry Offsets
  1522. ;
  1523. ;    Environment      = 6
  1524. ;
  1525.  
  1526.     mov    word ptr cs:S_di, di        ; Save registers
  1527.     mov    word ptr cs:S_si, si
  1528.     mov    word ptr cs:S_ds, ds
  1529.  
  1530. ;
  1531. ; Save the length of the current MCB block;
  1532. ;
  1533.  
  1534.     mov    ax, word ptr ds:__psp
  1535.     dec    ax
  1536.     mov    word ptr cs:N_mcb, ax        ; Save MCB address for swap out
  1537.  
  1538. ; Calculate low mem start for extended memory
  1539.  
  1540.     mov    bx, ax                ; Save copy
  1541.     mov    cl, 4                ; mult low order by 16
  1542.     shl    ax, cl
  1543.     mov    word ptr cs:SW_LMstart, ax    ; Save low order
  1544.     mov    cl, 12                ; div by 16 ** 3
  1545.     shr    bx, cl
  1546.     mov    byte ptr cs:SW_LMstart + 2, bl    ; Save low order
  1547.  
  1548. ;
  1549. ; Set up Environment segment in execute structure
  1550. ;
  1551.  
  1552.     mov    bx, cs
  1553.     mov    ax, offset Env_OWrite
  1554.     mov    cl, 4
  1555.     shr    ax, cl
  1556.     add    ax, bx
  1557.     mov    word ptr cs:exec_env, ax    ; Save Env seg.
  1558.  
  1559. ;
  1560. ; Set up rest of execute structure
  1561. ;
  1562.  
  1563.     mov    word ptr cs:exec_cseg, cs    ; Command line address
  1564.     mov    word ptr cs:exec_f1seg, cs    ; FCB 1 address
  1565.     mov    word ptr cs:exec_f2seg, cs    ; FCB 2 address
  1566.  
  1567. ;
  1568. ; Generate the FCBs
  1569. ;
  1570.  
  1571.     mov    ax, cs        ; Set up segments
  1572.     mov    ds, ax
  1573.     mov    es, ax
  1574.  
  1575.     mov    ax, 02901H    ; Set up FCB interrupt
  1576.     mov    si, offset _cmd_line + 1
  1577.     mov    di, offset FCB1    ; FCB 1;
  1578.  
  1579.     int    021H        ; Execute the interrupt
  1580.  
  1581.     mov    ax, cs        ; Set up segment
  1582.     mov    es, ax
  1583.  
  1584.     mov    ax, 02901H    ; Reset AX cause errors are ignored
  1585.     mov    di, offset FCB2    ; FCB 2;
  1586.  
  1587.     int    021H        ; Execute the interrupt
  1588.  
  1589. ;
  1590. ; Copy out to the swap file
  1591. ;
  1592.  
  1593.     mov    bx, word ptr cs:_SW_fp        ; Load file handler
  1594.     mov    si, word ptr cs:_SW_Blocks    ; Load Number of blocks to read
  1595.     mov    ax, word ptr cs:N_mcb        ; Load the start address
  1596.  
  1597. ;
  1598. ;  Check for Partial write on disk swap file
  1599. ;
  1600.  
  1601.     cmp    word ptr cs: _SW_Mode, 1    ; Partial disk write ?
  1602.     jnz    SPart_Write
  1603.     cmp    word ptr cs: _SW_Pwrite, 0
  1604.     jz    SPart_Write
  1605.  
  1606.     mov    si, word ptr cs:_SW_SBlocks    ; Load Number of blocks to read
  1607.     mov    ax, word ptr cs:_etext        ; Load the start address
  1608.  
  1609. SPart_Write:
  1610.     push    ax
  1611.  
  1612. ; load up extended memory GDT for destination
  1613.  
  1614.     mov    ax, word ptr cs:_SW_EMstart
  1615.     mov    dl, byte ptr cs:_SW_EMstart + 2
  1616.     call    $GDT_dest_load
  1617.  
  1618. ;
  1619. ; set up DS register with start of start copy
  1620. ;
  1621.  
  1622.     pop    ax
  1623.     mov    ds, ax
  1624.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  1625.     mov    dl, byte ptr cs:SW_LMstart + 2
  1626.     call    $GDT_src_load
  1627.  
  1628. ;
  1629. ; Check for end of copy - BX contains the file handler for disk write
  1630. ;
  1631.  
  1632. $Write_loop:
  1633.     or    si, si
  1634.     jnz    $Write_L1
  1635.     jmp    $Write_Complete
  1636.  
  1637. ; OK - Copy next 0x4000 bytes - switch on device
  1638.  
  1639. $Write_L1:
  1640.     mov    ax, word ptr cs: _SW_Mode
  1641.     dec    ax
  1642.     jz    $W_disk
  1643.     dec    ax
  1644.     jnz    $Write_L2
  1645.     jmp    $W_extend
  1646. $Write_L2:
  1647.     dec    ax
  1648.     jnz    $W_xms
  1649.     jmp    $W_expand
  1650.  
  1651. ;
  1652. ; Write to XMS driver.  In this case, we do one write and let the driver
  1653. ; sort out the blocking
  1654. ;
  1655. $W_xms:
  1656.     xor    ax, ax
  1657.     mov    word ptr cs:XMS_SHandle, ax    ; Source - normal memory
  1658.     mov    word ptr cs:XMS_DHandle, bx    ; Dest - XMS
  1659.  
  1660.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset - zero
  1661.     mov    word ptr cs:XMS_Doffset + 2, ax
  1662.  
  1663.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset DS:0
  1664.     mov    ax, ds
  1665.     mov    word ptr cs:XMS_Soffset + 2, ax
  1666.  
  1667. ;
  1668. ; Set up number of bytes SW_Block * 16 * 1024
  1669. ;
  1670.  
  1671.     mov    ax, si
  1672.     mov    dx, si
  1673.     mov    cl, 14
  1674.     shl    ax, cl
  1675.     mov    cl, 2
  1676.     shr    dx, cl
  1677.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  1678.     mov    word ptr cs:XMS_Length + 2, dx
  1679.  
  1680.     mov    ah, 0BH                ; Set up parameters
  1681.     mov    dx, cs
  1682.     mov    ds, dx
  1683.     mov    si, offset XMS_DIF
  1684.     call    cs:[_SW_XMS_Driver]
  1685.     or    ax, ax
  1686.     jnz     $Write_Complete
  1687.  
  1688. ; XMS error - abort
  1689.     
  1690.     mov    ah, bl
  1691.     jmp    $Write_error
  1692.  
  1693. ;
  1694. ; Write to disk
  1695. ;
  1696. $W_disk:
  1697.     call    $Write_disk
  1698.  
  1699. ; Increment counter
  1700.  
  1701. $Write_Incr:
  1702.     dec    si            ; Decrement block count
  1703.     mov    ax, ds            ; Increment offset
  1704.     add    ax, 0400H
  1705.     mov    ds, ax
  1706.     jmp    $Write_loop
  1707.  
  1708. ; Write to extended memory
  1709.  
  1710. $W_extend:
  1711.     call    $Write_extend
  1712.     jc    $Write_error        ; NO - abort
  1713.  
  1714.     dec    si            ; Decrement block count
  1715.     call    $Inc_Extend
  1716.     jmp    $Write_loop
  1717.  
  1718. ; Write to expanded memory
  1719. ;    BX - handler
  1720. ;    SI - count
  1721. ;    DS - source segment
  1722. ;
  1723. $W_expand:
  1724.     call    $map_ems_page        ; Map in the current EMS page
  1725.     jnz    $Write_error
  1726.  
  1727.     push    ds            ; Save DS and SI
  1728.     push    si
  1729.     mov    es, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  1730.     xor    si, si            ; Clear start
  1731.     xor    di, di
  1732.     mov    cx, 02000H        ; move 16K
  1733.     pushf                ; Save direction flag
  1734.     cld
  1735.     rep movsw
  1736.     popf                ; Restore direction flag
  1737.     pop    si            ; And DS, SI
  1738.     pop    ds
  1739.     jmp    $Write_Incr        ; Increment DS and dec SI
  1740.  
  1741. ;
  1742. ; Error - abort.  The error code is in AH.
  1743. ;
  1744.  
  1745. $Write_error:
  1746.     mov    ds, word ptr cs:S_ds    ; Restore DS
  1747.     mov    al, ah
  1748.     xor    ah, ah
  1749.     mov    word ptr ds:_errno, ax    ; Save error code
  1750.  
  1751. $Write_Error1:
  1752.     mov    ax, 0FFFEH
  1753.     jmp    $SA_spawn_Exit        ; Exit
  1754.  
  1755. ;
  1756. ; Swap file is now written, set up environment.  If this was a partial
  1757. ; write, we need to write the first 4K.
  1758. ;
  1759.  
  1760. $Write_Complete:
  1761.     cmp    word ptr cs: _SW_Mode, 1    ; Partial disk write ?
  1762.     jnz    S1Part_Write
  1763.     cmp    word ptr cs: _SW_Pwrite, 0
  1764.     jz    S1Part_Write
  1765.  
  1766.     mov    ax, 04200H            ; Set seek
  1767.     xor    dx, dx
  1768.     xor    cx, cx
  1769.     int    021H
  1770.     jnc    $Write_C1            ; Abort - swap file error
  1771.     jmp    $Map_error
  1772.  
  1773. $Write_C1:
  1774.     mov    ax, word ptr cs:N_mcb        ; Load the start address
  1775.     mov    ds, ax
  1776.     call    $Write_disk
  1777.  
  1778. ;
  1779. ; Go to the no-overwrite part.
  1780. ;
  1781.  
  1782. S1Part_Write:
  1783.     jmp    SA_spawn1
  1784. _SA_spawn    endp
  1785.  
  1786. ;
  1787. ; WRITE DISK FUNCTION
  1788. ;
  1789. ;    BX - file handler
  1790. ;    SI - Block count
  1791. ;    DS - Output data segement
  1792. ;
  1793.  
  1794. $Write_disk    proc    near
  1795.  
  1796.     mov    ax, 04000H        ; Set up to write
  1797.     mov    cx, ax            ; Load count
  1798.     xor    dx, dx            ; Clear start address
  1799.     push    bx            ; Save FP
  1800.     push    si            ; Save count and Data Segment
  1801.  
  1802.     int    021H            ; Write the data
  1803.  
  1804.     pop    si            ; Restore Regs
  1805.     pop    bx
  1806.     jnc    $Write_disk1        ; NO error - continue
  1807.  
  1808. ;
  1809. ; Error - abort
  1810. ;
  1811.     mov    ds, word ptr cs:S_ds    ; Restore DS
  1812. IFDEF __TURBOC__
  1813.     xor    ah, ah
  1814.     push    ax
  1815.     call    far ptr __IOERROR    ; Map the error
  1816. ELSE
  1817.     mov    ah, al
  1818.     call    far ptr __maperror    ; Map the error
  1819. ENDIF
  1820.     jmp    $Write_Error1
  1821.  
  1822. ; Check for 16K write
  1823.  
  1824. $Write_disk1:
  1825.     cmp    ax, 04000H
  1826.     jnz    $Write_disk2
  1827.     ret
  1828.  
  1829. $Write_disk2:
  1830.     mov    ax,01c1cH        ; Set disk full
  1831.     jmp    $Write_error        ; NO - abort
  1832.  
  1833. $Write_disk    endp
  1834.  
  1835. ;
  1836. ; END OF SWAPPER
  1837. ;
  1838.  
  1839. SH0_TEXT    ends
  1840.         end
  1841.